#include<iostream>
#include"func.h"
#include<opencv2/imgcodecs.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/objdetect.hpp>
#include<string>
#include<vector>

using namespace std;
using namespace cv;

void myprint()
{
    cout<<"test access"<<endl;
}

void yansekongjian()
{
    Mat img = imread("/home/zhanjiabin/桌面/task/documentscanner/paper.jpg");
    Mat img32;
    img.convertTo(img32,CV_32F,1/255.0,0);//图像数据类型转换函数（转换类型后输出图像，转换图像的数据类型，转换过程的缩放因子，转换过程的偏置因子）
    Mat HSV,HSV32;
    cvtColor(img,HSV,COLOR_BGR2HSV);
    cvtColor(img32,HSV32,COLOR_BGR2HSV);
    Mat gray0,gray1;
    cvtColor(img,gray0,COLOR_BGR2GRAY);
    cvtColor(img,gray1,COLOR_BGR2GRAY);

    imshow("img",img);
    imshow("img32",img32);
    imshow("HSV",HSV);
    imshow("HSV32",HSV32);
    imshow("gray0",gray0);
    imshow("gray1",gray1);
    waitKey(0);


}

void tongdaofenlihebing()
{

    Mat img = imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    Mat img32;

    img.convertTo(img32,CV_32F,1/255.0,0);//图像数据类型转换函数（转换类型后输出图像，转换图像的数据类型，转换过程的缩放因子，转换过程的偏置因子）
    
    Mat gray0,gray1;
    cvtColor(img,gray0,COLOR_BGR2GRAY);//颜色通道转换函数（原始图像，目标图像，色彩空间转换标志）
    cvtColor(img,gray1,COLOR_BGR2GRAY);

    Mat imgs[3];
    split(img,imgs);//分离图像通道函数（原始图像，分离后图像数组<大小要与图像通道数相同>）

    Mat img0,img1,img2;

    img0=imgs[0];
    img1=imgs[1];
    img2=imgs[2];

    Mat img_h;
    merge(imgs,3,img_h);//多通道合并函数（要合并的数组向量vector<每个图像尺寸和数据类型相同>,合并后输出的图像）

    Mat zero = Mat::zeros(Size(img.cols,img.rows),CV_8UC1);
    vector<Mat> imgsV;
    imgsV.push_back(img0);
    imgsV.push_back(zero);
    imgsV.push_back(zero);

    Mat imgsVH;
    merge(imgsV,imgsVH);

    imshow("img",img);
    // imshow("img32",img32);
    // imshow("gray0",gray0);
    // imshow("gray1",gray1);
    imshow("img0",img0);
    imshow("img1",img1);
    imshow("img2",img2);
    imshow("img_h",img_h);
    imshow("imgsVH",imgsVH);

    waitKey(0);    
}

void liangtuxiangsubijiao()
{
    Mat img=imread("/home/zhanjiabin/桌面/task/study/test2.jpg");//读入原始图像
    Mat white=imread("/home/zhanjiabin/桌面/task/study/white.jpg");//读入白色掩码
    Mat black=imread("/home/zhanjiabin/桌面/task/study/black.jpg");//读入黑色掩码

    //白色（255）最大，黑色（0）最小，max函数保留白色，min函数保留黑色
    Mat Min,Max;
    min(img,white,Min);//像素比较函数（原始图像1，原始图像2<通道数和数据类型与原始图像1一致>，比较后输出图像）
    max(img,black,Max);

    Mat gray,gray_black,gray_white;
    cvtColor(img,gray,COLOR_BGR2GRAY);//将img彩色图像转换为单通道图像
    cvtColor(black,gray_black,COLOR_BGR2GRAY);
    cvtColor(white,gray_white,COLOR_BGR2GRAY);

    double minVal,maxVal;//定义两个变量存放最大值和最小值
    Point MinLoc,MaxLoc;//定义两个坐标存放最大和最小值坐标

    minMaxLoc(gray,&minVal,&maxVal,&MinLoc,&MaxLoc);//最大最小值寻找函数(要寻找的图像，存放最小值的指针，存放最大值的指针，存放最小值坐标的指针，存放最大值坐标的指针)
    cout<<"minVal="<<minVal<<endl;
    cout<<"maxVal="<<maxVal<<endl;
    cout<<"MinLoc"<<"("<<MinLoc.x<<","<<MinLoc.y<<")"<<endl;
    cout<<"MaxLoc"<<"("<<MaxLoc.x<<","<<MaxLoc.y<<")"<<endl;
    cout<<"\n"<<endl;

    minMaxLoc(gray,&minVal,&maxVal,&MinLoc,&MaxLoc,gray_black);//最大最小值寻找函数(要寻找的图像，存放最小值的指针，存放最大值的指针，存放最小值坐标的指针，存放最大值坐标的指针,掩码率矩阵)
    cout<<"minVal="<<minVal<<endl;
    cout<<"maxVal="<<maxVal<<endl;
    cout<<"MinLoc"<<"("<<MinLoc.x<<","<<MinLoc.y<<")"<<endl;
    cout<<"MaxLoc"<<"("<<MaxLoc.x<<","<<MaxLoc.y<<")"<<endl;
    cout<<"\n"<<endl;

    minMaxLoc(gray,&minVal,&maxVal,&MinLoc,&MaxLoc,gray_black);//最大最小值寻找函数(要寻找的图像，存放最小值的指针，存放最大值的指针，存放最小值坐标的指针，存放最大值坐标的指针)
    cout<<"minVal="<<minVal<<endl;
    cout<<"maxVal="<<maxVal<<endl;
    cout<<"MinLoc"<<"("<<MinLoc.x<<","<<MinLoc.y<<")"<<endl;
    cout<<"MaxLoc"<<"("<<MaxLoc.x<<","<<MaxLoc.y<<")"<<endl;
    cout<<"\n"<<endl;


    imshow("img",img);
    imshow("Min",Min);
    imshow("Max",Max);
    imshow("gray",gray);
    
    waitKey(0);

}

void xiangsuluojiyunsuan()
{
    Mat a=(Mat_<uchar>(1,2)<<0,5);//枚举法对1*2的a矩阵赋值0和5
    Mat b=(Mat_<uchar>(1,2)<<0,6);//枚举法对1*2的b矩阵赋值0和5

    Mat Xor,Or,Not,And;

    bitwise_not(a,Not);//对a矩阵进行非运算，矩阵非运算函数（原矩阵，非运算后输出的矩阵）

    cout<<"a Not    "<<Not<<endl;

    bitwise_and(a,b,And);//矩阵与运算函数（矩阵1，矩阵2<尺寸、通道数、数据类型与矩阵1一致，与运算后输出矩阵>

    cout<<"a b and  "<<And<<endl;

    bitwise_or(a,b,Or);//矩阵或运算函数（矩阵1，矩阵2<尺寸、通道数、数据类型与矩阵1一致，或运算后输出矩阵>

    cout<<"a b or   "<<Or<<endl;

    bitwise_xor(a,b,Xor);//矩阵异或运算函数（矩阵1，矩阵2<尺寸、通道数、数据类型与矩阵1一致，异或运算后输出矩阵>

    cout<<"a,b.xor  "<<Xor<<endl;

    Mat img=imread("/home/zhanjiabin/桌面/task/study/test2.jpg");
    Mat mark=imread("/home/zhanjiabin/桌面/task/study/white.jpg");
    Mat result;

    bitwise_and(img,mark,result);
    
    Mat img_inv;
    // bitwise_not(img,img_inv);

    cvtColor(mark,mark,COLOR_BGR2GRAY);//将mark转化为灰度图

    bitwise_not(img,img_inv,mark);//（矩阵1，矩阵2，遮罩矩阵）

    Mat mark_black = imread("/home/zhanjiabin/桌面/task/study/black.jpg");

    min(img,mark_black,img);

    img=img+img_inv;

    imshow("result",result);
    imshow("img_inv",img_inv);
    imshow("img",img);
    waitKey(0);

}

void erzhihua()
{
    Mat img=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    if(img.empty())
    {
        cout<<"找不到图像"<<endl;
    }

    //将图像转为灰度图
    Mat gray;
    cvtColor(img,gray,COLOR_BGR2GRAY);

    Mat img_B,img_B_V,gray_B,gray_B_V,gray_T,gray_T_V,gray_TRUNC;

    //彩图二值化
    threshold(img,img_B,125,255,THRESH_BINARY);//小于125的部分为0,图像二值化函数(原图，二值化后图像，最低值，最高值，二值化类型)
    threshold(img,img_B_V,125,255,THRESH_BINARY_INV);//大于125的部分为0
    imshow("img_B",img_B);
    imshow("img_B_V",img_B_V);

    //灰度图二值化
    threshold(gray,gray_B,125,255,THRESH_BINARY);//小于125的部分为0
    threshold(gray,gray_B_V,125,255,THRESH_BINARY_INV);//大于125的部分为0
    imshow("gray_B",gray_B);
    imshow("gray_B_V",gray_B_V);

    //灰度图tozero变换
    threshold(gray,gray_T,125,255,THRESH_TOZERO);//小于125的部分为0
    threshold(gray,gray_T_V,125,255,THRESH_TOZERO_INV);//大于125的部分为0
    imshow("gray_T",gray_T);
    imshow("gray_T_V",gray_T_V);

    //灰度图大律法和三角形法二值化
    Mat img2=imread("/home/zhanjiabin/桌面/task/study/test2.jpg");
    Mat gray2;
    cvtColor(img2,gray2,COLOR_BGR2GRAY);
    Mat gray2_Thr_0,gray2_Thr_T;
    threshold(gray2,gray2_Thr_0,100,255,THRESH_BINARY|THRESH_OTSU);//大律法寻找binary变换的阈值
    threshold(gray2,gray2_Thr_T,125,255,THRESH_BINARY|THRESH_TRIANGLE);//三角形法寻找binary变换的阈值
    imshow("gray2",gray2);
    imshow("gray2_Thr_0",gray2_Thr_0);
    imshow("gray2_Thr_T",gray2_Thr_T);

    Mat adp_m,adp_g;
    adaptiveThreshold(gray2,adp_m,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,55,0);//将图像在55的像素邻域内用均值法自适应寻找二值化阈值(小于阈值置为0)，输出到adp_m中
    //自适应图像二值化函数(原图，二值化后图，最大值，自适应确定阈值方法，二值化标志，自适应像素邻域大小，平均值中减去的常数)<只能用于灰度图>
    adaptiveThreshold(gray2,adp_g,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY,55,0);//将图像在55的像素邻域内用高斯法自适应寻找二值化阈值(小于阈值置为0)，输出到adp_m中
    //自适应图像二值化函数(原图，二值化后图，最大值，自适应确定阈值方法，二值化标志，自适应像素邻域大小，平均值中减去的常数)
    imshow("adp_m",adp_m);
    imshow("adp_g",adp_g);

    waitKey(0);


    
}

void LUTchazhaobiao()
{
    //LUT查找表第一层
    uchar lutFrist[256];
    for(int i=0;i<256;i++)
    {
        if(i<=100)
        lutFrist[i]=0;
        if(i>100 && i<200)
        lutFrist[i]=100;
        if(i>200)
        lutFrist[i]=255;
    }
    Mat lutone(1,256,CV_8UC1,lutFrist);
    
    //LUT查找表第二层
    uchar lutSecond[256];
    for(int i=0;i<256;i++)
    {
        if(i<=100)
        lutSecond[i]=0;
        if(i>100 && i<=150)
        lutSecond[i]=100;
        if(i>150 && i<200)
        lutSecond[i]=150;
        if(i>200)
        lutSecond[i]=255;
    }
    Mat luttwo(1,256,CV_8UC1,lutSecond);

    //LUT查找表第三层
    uchar lutThird[256];
    for(int i=0;i<256;i++)
    {
        if(i<=100)
        lutThird[i]=100;
        if(i>100 && i<=200)
        lutThird[i]=200;
        if(i>200)
        lutThird[i]=255;
    }
    Mat lutthree(1,256,CV_8UC1,lutThird); 

    vector<Mat>mergeMats;//定义矩阵vector容器存放三个查找表
    mergeMats.push_back(lutone);//pushback是尾插
    mergeMats.push_back(luttwo);
    mergeMats.push_back(lutthree);
    Mat LutTree;//定义矩阵存放三个查找表合并后结果
    merge(mergeMats,LutTree);//合并三个查找表

    Mat img=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    if(img.empty())
    {
        cout<<"图片路径错误"<<endl;
    }
    Mat gray,out0,out1,out2;
    cvtColor(img,gray,COLOR_BGR2GRAY);
    LUT(gray,lutone,out0);//LUT查找表映射函数(输入图片<通道数与查找表层数相同>，查找表<256个像素>，输出图片)
    LUT(img,lutone,out1);
    LUT(img,LutTree,out2);

    imshow("out0",out0);
    imshow("out1",out1);
    imshow("out2",out2);
    waitKey(0);
}

void tuxiangchicunbianhuan()
{
    Mat gray=imread("/home/zhanjiabin/桌面/task/study/test.jpg",IMREAD_GRAYSCALE);

    Mat sma11Img,bigImg0,bigImg1,bigImg2;
    resize(gray,sma11Img,Size(15,15),0,0,INTER_AREA);//更改图片尺寸函数(原图，输出图，新尺寸，水平轴变换倍数，垂直轴变换倍数，插值方法标志)//缩小图像
    resize(sma11Img,bigImg0,Size(30,30),0,0,INTER_NEAREST);//最临近插值
    resize(sma11Img,bigImg1,Size(30,30),0,0,INTER_LINEAR);//双线性插值
    resize(sma11Img,bigImg2,Size(30,30),0,0,INTER_CUBIC);//双三次插值

    Mat img_x,img_y,img_xy;
    flip(gray,img_x,0);//图像翻转函数(输入图，输出图，翻转方式标志< >0y翻转，=0x翻转，小于0xy翻转 >)
    flip(gray,img_y,1);
    flip(gray,img_xy,-1);

    Mat img00=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    Mat img01=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    Mat img10=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    Mat img11=imread("/home/zhanjiabin/桌面/task/study/test.jpg");

    Mat img0,img,img1;
    hconcat(img00,img01,img0);//图像横接函数(输入图1，输入图2<与1同高>，输出图)
    hconcat(img10,img11,img1);

    vconcat(img0,img1,img);//图像竖接函数(输入图1，输入图2<与1同宽>,输出图)

    imshow("gray",gray);
    imshow("sma11Img",sma11Img);
    imshow("bigImg0",bigImg0);
    imshow("bigImg1",bigImg1);
    imshow("bigimg2",bigImg2);
    imshow("img_x",img_x);
    imshow("img_y",img_y);
    imshow("img_xy",img_xy);
    imshow("img",img);

    waitKey(0);

}

void fangshebianhuan()
{
    Mat img=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    if(img.empty())
    {
        cout<<"未找到图片"<<endl;
    }

    Mat rotation0,img_warp0;

    double angle=30;
    Size dst_size(img.rows,img.cols);//定义尺寸(img高度<高度>，img宽度<宽度>)
    Point2f center(img.rows/2.0,img.cols/2.0);//定义点(高度，宽度)

    rotation0=getRotationMatrix2D(center,angle,1);//计算仿射变换矩阵函数(旋转中心点，旋转角度，缩放比例<不缩放为>1)

    warpAffine(img,img_warp0,rotation0,dst_size);//仿射变换函数(原图，变换后图，仿射变换矩阵，输出图像尺寸)

    //定义三个点进行仿射变换
    Point2f src_points[3];//定义原图三个点数组
    Point2f dst_points[3];//定义仿射后三个点数组

    //对仿射前后三个点赋值
    src_points[0]=Point2f(0,0);
    src_points[1]=Point2f(0,(float)(img.cols-1));
    src_points[2]=Point2f((float)(img.rows-1),(float)(img.cols)*0.20);
    dst_points[0]=Point2f((float)(img.rows)*0.11,(float)(img.cols)*0.20);
    dst_points[0]=Point2f((float)(img.rows)*0.15,(float)(img.cols)*0.70);
    dst_points[0]=Point2f((float)(img.rows)*0.81,(float)(img.cols)*0.85);

    Mat rotation1,img_warp1;
    rotation1=getAffineTransform(src_points,dst_points);//根据对应点求仿射矩阵(放射前三个点数组，仿射后三个点数组)
    warpAffine(img,img_warp1,rotation1,dst_size);


    imshow("img_warp0",img_warp0);
    imshow("img_warp1",img_warp1);
    waitKey(0);
}

void toushibianhuan1()
{
    Mat img=imread("/home/zhanjiabin/桌面/task/study/0512_1.jpg");
    if(img.empty())
    {
        cout<<"无法读取文件"<<endl;
    }

    Point2f src_points[4];//原图的四个角点坐标
    Point2f dst_points[4];//输出图对应四个角点坐标

    src_points[0]=Point2f (585.0,162.0);
    src_points[1]=Point2f (815.0,217.0);
    src_points[2]=Point2f (746.0,509.0);
    src_points[3]=Point2f (449.0,437.0);

    dst_points[0]=Point2f (0.0,0.0);
    dst_points[0]=Point2f (291.0,0.0);
    dst_points[0]=Point2f (291.0,284.0);
    dst_points[0]=Point2f (0.0,284.0);

    Mat rotation,img_warp;

    rotation=getPerspectiveTransform(src_points,dst_points);//计算透视变换矩阵函数(原图四个点，输出图四个点)
    warpPerspective(img,img_warp,rotation,img.size());//透视变换矩阵函数(原图，输出图，透视变换矩阵，输出图尺寸)

    imshow("img",img);
    imshow("img_warp",img_warp);
    waitKey(0);
}

